package cn.czh0123.redis.service.impl;

import cn.czh0123.domain.WallpaperRecord;
import cn.czh0123.enums.WallpaperOperateType;
import cn.czh0123.exception.BusinessException;
import cn.czh0123.mapper.WallpaperRecordMapper;
import cn.czh0123.msg.WallpaperCodeMsg;
import cn.czh0123.redis.service.IWallpaperOperateRedisService;
import cn.czh0123.redis.service.IWallpaperStatisticsRedisService;
import cn.czh0123.redis.vo.WallpaperStatisticsVO;
import cn.czh0123.utils.RedisKeys;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author: czh
 * @description:
 * @date: 2024/3/30 19:19
 */
@Slf4j
@Service
public class WallpaperOperateRedisServiceImpl implements IWallpaperOperateRedisService {
    @Resource
    private WallpaperRecordMapper wallpaperRecordMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private IWallpaperStatisticsRedisService wallpaperStatisticsRedisService;

    @Override
    public void saveWallpaperOperateRecord() {
        String key = RedisKeys.WALLPAPER_OPERATE_RECORD.join();
        int batchSize = 100;
        List<String> records;

        while (true) {
            records = stringRedisTemplate.opsForList().range(key, 0, batchSize-1);
            if (records == null || records.isEmpty()) {
                break;
            }

            List<WallpaperRecord> wallpaperRecords = Lists.newArrayList();
            for (String recordJson : records) {
                WallpaperRecord record = JSON.parseObject(recordJson, WallpaperRecord.class);
                wallpaperRecords.add(record);
            }
            wallpaperRecordMapper.batchInsert(wallpaperRecords);
            stringRedisTemplate.opsForList().trim(key, batchSize, -1);
        }
    }

    @Override
    public List<WallpaperRecord> getWallpaperOperateRecordByWallpaperId(Long wallpaperId) {
        if (wallpaperId == null) {
            throw new BusinessException(WallpaperCodeMsg.NOT_FOUND_ID);
        }
        String key = RedisKeys.WALLPAPER_OPERATE_RECORD.join();
        List<String> range = stringRedisTemplate.opsForList().range(key, 0, -1);

        if (range == null || range.isEmpty()) {
            return Lists.newArrayList();
        }

        return range.stream()
                .map(jsonStr -> JSON.parseObject(jsonStr, WallpaperRecord.class))
                .filter(record -> record.getWallpaperId().equals(wallpaperId))
                .collect(Collectors.toList());
    }

    @Override
    public void operate(Long wallpaperId, WallpaperOperateType wallpaperOperateType) {
        try {
            WallpaperStatisticsVO vo = wallpaperStatisticsRedisService.getWallpaperStatistics(wallpaperId);
            switch (wallpaperOperateType) {
                case VIEW:
                    vo.setViewNum(vo.getViewNum() + 1);
                    break;
                case COMMENT:
                    vo.setCommentNum(vo.getCommentNum() + 1);
                    break;
                case COLLECT:
                    vo.setFavorNum(vo.getFavorNum() + 1);
                    break;
                case LIKE:
                    vo.setLikeNum(vo.getLikeNum() + 1);
                    break;
                case DOWNLOAD:
                    vo.setDownloadNum(vo.getDownloadNum() + 1);
                    break;
            }
            wallpaperStatisticsRedisService.setWallpaperStatistics(vo);

            WallpaperRecord record = new WallpaperRecord();
            if (StpUtil.isLogin()) {
                record.setUserId(StpUtil.getLoginIdAsLong());
            }
            record.setWallpaperId(wallpaperId);
            record.setOperateType(wallpaperOperateType.getCode());
            record.setOperateTime(new Date());
            String recordJson = JSON.toJSONString(record);

            String key = RedisKeys.WALLPAPER_OPERATE_RECORD.join();
            stringRedisTemplate.opsForList().rightPush(key, recordJson);
            stringRedisTemplate.expire(key, RedisKeys.WALLPAPER_OPERATE_RECORD.getTime(), TimeUnit.SECONDS);
        } catch (Exception e) {
            log.error("记录操作失败！", e);
        }
    }

}
